package Advanced;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import demo04Package.demo04GenericClass;
import demo04Package.demo04GenericInterface;
import demo04Package.demo04GenericInterfaceImpl;
import demo04Package.demo04GenericMethod;

import java.util.ArrayList;

public class demo04Collection集合和Iterator迭代器与泛型 {

	public static void main(String[] args) {
//		collectionFrame();
//		iterator();
//		forEach();
//		generic();
//		genericUse();
		douDiZhu();
		  
	}
	public static void collectionFrame() {
		/* 学习集合的目标：
		 * 		1、会使用集合存储数据
		 * 		2、会遍历集合，把数据取出来
		 * 		3、掌握每种集合的特性
		 * 集合框架的学习方式：
		 * 		1、学习顶层：学习顶层接口/抽象类中共性的方法，所有的子类都可以使用
		 * 		2、使用底层：顶层不是接口就是抽象类，无法创建对象使用，需要使用底层的子类创建对象使用
		 * Collection接口：
		 * 		定义的是所有单列集合中共性的方法，所有的单列集合都可以使用共性的方法，没有索引的方法
		 * List接口：
		 *  	1、有序的集合(存储和取出元素的顺序相同)
		 *  	2、允许存储重复的元素
		 *  	3、有索引，可以使用普通的for循环遍历
		 * Set接口：
		 * 		1、不允许存储重复元素
		 * 		2、没有索引(不能使用普通的for循环遍历)
		 * 共性的方法：
		 * 		public boolean add(E e):把给定的对象添加到当前集合中
		 * 		public void clear():清空集合中所有的元素
		 * 		public boolean remove(E e):把给定对象在当前集合中删除
		 * 		public boolean contains(E e):判断当前集合中是否包含给定的对象
		 * 		public boolean isEmpty():判断当前集合是否为空
		 * 		public int size():返回集合元素的个数
		 * 		public Object[] toArray():把集合中的元素，存储到数组中
		 * */
		//使用多态创建一个集合对象
		Collection<String> coll = new ArrayList<>();
		System.out.println(coll);//重写了toString方法
		
		//public boolean add(E e):把给定的对象添加到当前集合中
		boolean b1 = coll.add("张三");
		coll.add("李四");
		System.out.println("b1:" + b1);
		System.out.println(coll);
		System.out.println("=========================");
		
		//public boolean remove(E e):把给定对象在当前集合中删除
		coll.add("abc");
		coll.add("def");
		boolean b2 = coll.remove("abc");
		boolean b3 = coll.remove("xyz");//若是集合中没有给定的元素则返回false
		System.out.println("b2:" + b2 + "    " + "b3:" + b3);
		System.out.println(coll);
		System.out.println("=========================");
		
		//public boolean contains(E e):判断当前集合中是否包含给定的对象
		boolean b4 = coll.contains("def");
		boolean b5 = coll.contains("abc");
		System.out.println("b4:" + b4 + "    " + "b5:" + b5);
		System.out.println(coll);
		System.out.println("=========================");
		
		//public boolean isEmpty():判断当前集合是否为空
		boolean b6 = coll.isEmpty();
		System.out.println("b6: " + b6);
		System.out.println("===========================");
		
		//public int size():返回集合元素的个数
		int size = coll.size();
		System.out.println("size:" + size);
		System.out.println("============================");
		
		//public Object[] toArray():把集合中的元素，存储到数组中
		Object[] arr = coll.toArray();
		for(int i = 0;i < arr.length;i++) {
			System.out.println(arr[i]);
		}
		System.out.println("============================");
		
		//public void clear():清空集合中所有的元素,但是不删除集合，集合还存在
		System.out.println(coll);
		coll.clear();
		System.out.println(coll);
		System.out.println(coll.isEmpty());
		
		
	}
	public static void iterator() {
		/* java.util.Iterator接口：迭代器(对集合进行遍历)
		 * 迭代的概念：
		 * 		即Collection集合元素的通用获取方式，在取出元素之前先要判断集合中有没有元素，如果有，就把这个元素取出来
		 * 		继续再判断，如果还有就再取出来，一直到集合中的所有元素全部取出，这种取出方式专业术语称为迭代
		 * 两个常用的方法：
		 * 		boolean hasNext()如果仍有元素可以迭代，则返回true
		 * 			判断集合中还有没有下一个元素
		 * 		E next()返回迭代的下一个元素
		 * 			取出集合中的下一个元素
		 * Iterator迭代器，是一个接口，我们无法直接使用，需要使用Iterator接口的实现类对象
		 * Collection接口中有一个方法，叫iterator(),这个方法返回的就是迭代器的实现类对象
		 * 		Iterator<E> iterator() 返回在此Collection的元素上进行迭代的迭代器
		 * 
		 * 使用步骤：
		 * 		1、使用集合中的方法：Iterator()获取迭代器的实现类对象，使用Iterator接口接收(多态)
		 * 			Iterator<E>接口也是有泛型的，迭代器的泛型和集合的泛型要保持一致
		 * 		2、使用Iterator接口中的方法hasNext()判断还有没有下一个元素
		 * 		3、使用Iterator接口中的方法next()取出集合中的下一个元素
		 * */
		
		Collection<String> coll = new ArrayList<String>();
		coll.add("姚明");
		coll.add("科比");
		coll.add("麦迪");
		coll.add("詹姆斯");
		coll.add("艾弗森");
		
		//1、使用集合中的方法：Iterator()获取迭代器的实现类对象，使用Iterator接口接收(多态)
		Iterator<String> it = coll.iterator();//会把指针(索引)指向集合的-1索引
		
		//2、使用Iterator接口中的方法hasNext()判断还有没有下一个元素
		boolean b = it.hasNext();
		System.out.println("b:" + b);
		
		//3、使用Iterator接口中的方法next()取出集合中的下一个元素
		String s = it.next();
		System.out.println("s:" + s);
		
		//使用while循环对集合中的元素进行迭代
		while(it.hasNext()) {
			s = it.next();
			System.out.println(s);
		}
	}
	public static void forEach() {
		/* 增强for循环：底层使用的也是迭代器，使用for循环的格式，简化了迭代器的书写
		 * 作用：用来遍历集合和数组
		 * 格式：
		 * 		for(集合/数组的数据类型 变量名 : 集合名/数组名){
		 * 			sout(变量名);
		 * }
		 * */
		int[] arr = {1,2,3,4,5};
		for(int i:arr) {
			System.out.println(i);
		}
		
		ArrayList<String> list = new ArrayList<String>();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");
		list.add("ddd");
		for(String str : list) {
			System.out.println(str);
		}
	}
	public static void generic() {
		/* 泛型：是一种未知的数据类型，当我们不知道使用什么数据类型的时候，可以用泛型，可以把泛型看作是一个接收数据类型的变量
		 * 创建对象的时候，就会确定泛型的数据类型，就是将对象的数据类型传递给泛型
		 * 创建集合对象，不使用泛型
		 * 		好处：
		 * 			集合不使用泛型，默认的类型就是Object类型，可以存储任意类型的数据
		 * 		弊端：
		 * 			不安全，会引发异常
		 * 创建集合对象，使用泛型
		 * 		好处：
		 * 			1、避免了类型转换的麻烦，存储的是什么类型，取出的就是什么类型
		 * 			2、把运行期异常，提升到了编译期
		 * 		弊端：
		 * 			2、泛型是什么类型，只能存储什么类型的数据
		 * */
//		@SuppressWarnings("rawtypes")
//		ArrayList list = new ArrayList();
//		list.add("abc");
//		list.add(21);
//		Iterator it = list.iterator();
//		while(it.hasNext()) {
//			Object obj = it.next();
//			System.out.println(obj);
//			String str = (String)obj;
//			System.out.println(str.length());
//		}
		ArrayList<String> list = new ArrayList<String>();
		list.add("abc");
		list.add("def");
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			String string = it.next();
			System.out.println(string);
		}
	}
	@SuppressWarnings("unchecked")
	public static void genericUse() {
		//定义含有泛型的类
		@SuppressWarnings("rawtypes")
		demo04GenericClass gc = new demo04GenericClass();
		gc.setName("只能是字符串");
		Object name = gc.getName();
		System.out.println(name);
		
		demo04GenericClass<Integer> gc2 = new demo04GenericClass<Integer>();
		gc2.setName(12);
		int name2 = gc2.getName();
		System.out.println(name2);
		
		demo04GenericClass<String> gc3 = new demo04GenericClass<String>();
		gc3.setName("dnsak");
		String str = gc3.getName();
		System.out.println(str);
		System.out.println("==================");
		
		/* 定义含有泛型的方法：泛型定义在方法的修饰符和返回值类型之间
		 * 格式：
		 * 		修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
		 * 			方法体;
		 * }
		 * 含有泛型的方法，在调用方法的时候确定泛型的数据类型，传递什么类型的参数，泛型就是什么类型
		 * */
		
		demo04GenericMethod gm = new demo04GenericMethod();
		gm.method01(10);
		gm.method01("sad");
		gm.method01(8.3);
		gm.method01(true);
		
		demo04GenericMethod.method02("静态方法，不建议创建对象使用");
		
		/* 含有泛型的接口第一种使用方式：定义接口的实现类，指定接口的泛型，创建实现类时确定泛型的类型
		 * 		public class demo04GenericInterfaceImpl implements demo04GenericInterface<String>{
		 * 			public void method(String e) {
		 *				System.out.println(e);
		 *			}
		 * 		}
		 * 含有泛型的接口第二种使用方式：接口使用什么泛型，实现类就使用什么泛型，创建对象时确定泛型的类型
		 * 		public class demo04GenericInterfaceImpl<E> implements demo04GenericInterface<E> {
		 *			public void method(E e) {
		 *				System.out.println(e);
		 *			}
		 *	}
		 */
		demo04GenericInterface<String> impl1 = new demo04GenericInterfaceImpl<String>();
		impl1.method("字符串");
		
		demo04GenericInterface<Integer> impl2 = new demo04GenericInterfaceImpl<Integer>();
		impl2.method(23);
		System.out.println("====================");
		
		/* 泛型的通配符：
		 * 		?:代表任意的数据类型
		 * 使用方式：
		 * 		不能创建对象使用，只能作为方法的参数使用
		 * */
		ArrayList<Integer> list01 = new ArrayList<Integer>();
		list01.add(1);
		list01.add(2);
		
		ArrayList<String> list02 = new ArrayList<String>();
		list02.add("a");
		list02.add("b");
		
		/* 定义一个方法，能遍历所有类型的ArrayList集合
		 * 这时候我们不知道ArrayList集合使用什么数据类型，可以使用泛型的通配符?来接收数据类型
		 * 注意：
		 * 		泛型没有继承概念的
		 * */
		printArray(list01);
		printArray(list02);
		
		/* 泛型的上限限定：? extends E   代表使用的泛型只能是E类型的子类/本身
		 * 泛型的下限限定：? super E     代表使用的泛型只能是E类型的父类/本身
		 * */
		
	}
	public static void printArray(ArrayList<?> list) {
		Iterator<?> it = list.iterator();
		while(it.hasNext()) {
			Object obj = it.next();//取出的元素是Object，可以接收任意的数据类型
			System.out.println(obj);
		}
	}
	//斗地主案例
	public static void douDiZhu() {
		//54张牌的集合
		ArrayList<String> poker = new ArrayList<String>();
		//花色的数组
		String[] decor = {"♥","♠","♣","♦"};
		//牌序号的数组
		String[] number = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
		//把大王小王存储到poker中
		poker.add("大王");
		poker.add("小王");
		//组装52张牌
		for(int i = 0;i < decor.length;i++) {
			for(int j = 0;j < number.length;j++) {
				poker.add(decor[i] + number[j]);
			}
		}
//		System.out.println(poker);
		//洗牌：使用Collections中的静态方法shuffle
		Collections.shuffle(poker);
		//定义3个玩家的集合和地主牌的集合
		ArrayList<String> play1 = new ArrayList<String>();
		ArrayList<String> play2 = new ArrayList<String>();
		ArrayList<String> play3 = new ArrayList<String>();
		ArrayList<String> playDZ = new ArrayList<String>();
		//发牌
		for(int i = 0;i < 51;i++) {
			if(i % 3 == 0) {
				play1.add(poker.get(i));
			}
			if(i % 3 == 1) {
				play2.add(poker.get(i));
			}
			if(i % 3 == 2) {
				play3.add(poker.get(i));
			}
		}
		playDZ.add(poker.get(51));
		playDZ.add(poker.get(52));
		playDZ.add(poker.get(53));
		
		//看牌
		System.out.println("刘青云： " + play1);
		System.out.println("王诗宁： " + play2);
		System.out.println("张三丰： " + play3);
		System.out.println("地主牌： " + playDZ);
	}
}
